/*
 * Copyright (c) 2001 Sun Microsystems, Inc.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *       Sun Microsystems, Inc. for Project JXTA."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Sun", "Sun Microsystems, Inc.", "JXTA" and "Project JXTA" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact Project JXTA at http://www.jxta.org.
 *
 * 5. Products derived from this software may not be called "JXTA",
 *    nor may "JXTA" appear in their name, without prior written
 *    permission of Sun.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL SUN MICROSYSTEMS OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of Project JXTA.  For more
 * information on Project JXTA, please see
 * <http://www.jxta.org/>.
 *
 * This license is based on the BSD license adopted by the Apache Foundation.
 *
 * $Id: SearchDemo.java,v 1.8 2002/04/10 15:30:40 rmjohnson Exp $
 */

package net.jxta.test;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

import java.lang.reflect.InvocationTargetException;
import java.io.File;
import java.io.InputStream;
import java.io.IOException;
import java.util.Vector;

import net.jxta.document.MimeMediaType;
import net.jxta.document.Advertisement;

import net.jxta.peergroup.PeerGroup;
import net.jxta.peergroup.PeerGroupFactory;
import net.jxta.exception.PeerGroupException;

import net.jxta.impl.peergroup.Platform;
import net.jxta.impl.peergroup.GenericPeerGroup;

import net.jxta.share.*;
import net.jxta.share.client.*;
import net.jxta.share.metadata.*;

/**
 * A simple applications that demonstrates how to search for content that is
 * being shared by other peers using CMS.
 * 
 * @see ShareDemo
 * @see MetadataSearchDemo
 * @see net.jxta.share.client.ListContentRequest
 * 
 * @version $Revision: 1.8 $
 */
public class SearchDemo {

    private PeerGroup netPeerGroup  = null;
    
    static public void main(String args[]) {
	//start SearchDemo
	new SearchDemo();
    }

    public SearchDemo() {
	startJxta();
	
	SearchWindow window = new SearchWindow();
	window.setVisible(true);
    }

    /**
     * initializes NetPeerGroup and the CMS
     */
    private void startJxta() {
	try {
	    // create, and Start the default jxta NetPeerGroup
	    netPeerGroup = PeerGroupFactory.newNetPeerGroup();
	    
	    //uncomment the following line if you want to start the app defined
	    // the NetPeerGroup Advertisement (by default it's the shell)
	    // in this case we want use jxta directly.
	    
	    // netPeerGroup.startApp(null);
			
	} catch (PeerGroupException e) {
	    // could not instanciate the group, print the stack and exit
	    System.out.println("fatal error : group creation failure");
	    e.printStackTrace();
	    System.exit(-1);
	}
    }

    /**
     * SearchWindow serves as the GUI for MetadataSearchDemo
     */
    public class SearchWindow extends Frame implements ActionListener {
	
	Button searchButton;
	Button viewButton;
	List resultList;
	
	MetadataQuery descQuery;
	MetadataQuery keywdQuery;
	
	//A ListContentRequest is needed to query other peers for
	//ContentAdvertisements
	ListContentRequest request = null;
	
	//an array is needed to store ContentAdvertisements returned by the
	//ListContentRequest
	ContentAdvertisement[] results = null;

	/**
	 * Initializes & arranges the window and its components.
	 */
	public SearchWindow() {
	    super("Search Demo");
	    setSize(450, 250);
	    addWindowListener(new WindowMonitor());

	    Panel toolbar = new Panel();
	    toolbar.setLayout(new FlowLayout(FlowLayout.LEFT));
	    
	    searchButton = new Button("Search");
	    searchButton.addActionListener(this);
	    toolbar.add(searchButton);
	    
	    viewButton = new Button("View Advertisement");
	    viewButton.addActionListener(this);
	    toolbar.add(viewButton);
	    
	    add(toolbar, BorderLayout.NORTH);
	    
	    resultList = new List();
	    add(resultList, BorderLayout.CENTER);
	}
	
	public void actionPerformed(ActionEvent e) {
	    System.out.println(e.getActionCommand());
	    //handle the event caused by the "Search" button being clicked
	    if (e.getSource().equals(searchButton)) {
		if (request != null) {
		    request.cancel();
		}

		//prompt the user for a search string
		String searchString = JOptionPane
		    .showInputDialog(this, "Enter a string to search for:");
	       
		//if the user doesn't enter anything, make the saerch string
		//empty.  This will cause peers to return all the
		//ContentAdvertisements that they are sharing.
		if(searchString == null)
		    searchString = "";
		
		//Initialize a ListContentRequest containing the search string
		// that was entered.
		request = new MyListRequest(netPeerGroup, searchString, this);
		
		//send the list request and wait for results to be returned
		request.activateRequest();
	    }else if (e.getSource().equals(viewButton)) {
		//handle the event caused by the "View Advertisement" button
		// being clicked.

		//figure out which content advertisement is selected, then
		//display it in an AdvertisementViewer
		int selectedIndex = resultList.getSelectedIndex();
		if((results != null) && (selectedIndex != -1)
		   && (results[selectedIndex] != null)) {
		    new AdvertisementViewer(results[selectedIndex]);
		}
	    }
	}
	
	/**
	 * This method filters through advertisements returned by other peers
	 * and then displays the matches in the list.
	 */
	protected void updateResults(ContentAdvertisement[] results) {
	    this.results = results;
	    
	    //erase all of the old results
	    resultList.removeAll();
	    
	    //insert the updated results into the list
	    for (int i=0; i<results.length; i++) {
		resultList.add(results[i].getName());
	    }
	}
    }
    
    /**
     * An implementation of ListContentRequest that will automatically update
     * a SearchWindow as ContentAdvertisements are returned.
     * 
     * @see ListContentRequest
     * @see CachedListContentRequest
     */
    class MyListRequest extends ListContentRequest {
	SearchWindow searchWindow = null;
	
	/**
	 * Initialize a list request that will be propagated throughout a given
	 * peer group.  Any ContentAdvertisement for which the string returned
	 * by getName() or getDescription() contains inSubStr
	 *  (case insensitive) is sent back in a list response. However, the
	 * list request isn't sent until activateRequest() is called.
	 * 
	 * @see net.jxta.share.client.ListContentRequest
	 * @see net.jxta.share.client.ListContentRequest#ListContentRequest(net.jxta.peergroup.PeerGroup, java.lang.String)
	 */
	public MyListRequest(PeerGroup group, String inSubStr
			     ,SearchWindow searchWindow) {
	    super(group, inSubStr);
	    this.searchWindow = searchWindow;
	}

	/**
	 * This function is called each time more results are received.
	 */
	public void notifyMoreResults() {
	    if (searchWindow != null) {
		//note: getResults() returns all of the ContentAdvertisements
		//received so far, not just the ones that were in the last list
		//response.
		searchWindow.updateResults(getResults());
	    }
	}
    }

    class WindowMonitor extends WindowAdapter {
	public void windowClosing(WindowEvent e) {
	    Window w = e.getWindow();
	    w.setVisible(false);
	    w.dispose();
	    System.exit(0);
	}
    }
}
